# -*- coding: utf-8 -*-
import socket,os,time
import select
from OpenSSL.SSL import Context,Connection,TLSv1_2_METHOD,ZeroReturnError,SysCallError
from concurrent.futures import ThreadPoolExecutor

def readFile(filenames):
    requests = []
    try:
        for filename in filenames:
            with open(filename, 'rb') as f:
                request = f.read()
                requests.append(request)
    except Exception as e:
            print ">> Exception >>",e.message
            raise e
    return requests

def concurrent_send(host,port,requests):
    requestnums = len(requests)
    hostiter = [host for i in range(requestnums)]
    portiter = [port for i in range(requestnums)]
    with ThreadPoolExecutor(max_workers=30) as executor:
        all  = executor.map(send,zip(requests,hostiter,portiter))
    for a in all:
        if len(a) >12:
            print a[9:12]

def send(args):
    s = send_Requests(args[1],args[2],args[0])
    s.init_socket()
    s.send()
    s.closeit()
    return s.response

class send_Requests:
    def __init__(self,host,port,request):
        self.host = host
        self.port = port
        self.requests= request
        self.response = ''
        self.rlist = []
        self.wlist = []
        self.elist = []
        self.protocoltype= 'ssl'
        if self.port == 8090 or self.port == 80:
            self.protocoltype = 'http'

    def init_socket(self):
        import struct
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        #设置SOL_SOCKET级别的接收缓冲区的大小(tcp的windows size大小)
        #self.sock.setsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF, 256)
        ###设置接收超时时间,比如SSL的握手设置1s会超时
        #self.sock.setsockopt(socket.SOL_SOCKET,socket.SO_RCVTIMEO,1)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,struct.pack('ii', 1, 0))
        if self.protocoltype.upper() == 'SSL':
            self._ssl_sock()
        else:
            self.sock.connect((self.host,self.port))

    def _write_sslkey(self):
        rootpath = os.getcwd().split('\\')[0]
        sslkeylogfile = os.environ.get('SSLKEYLOGFILE') if os.environ.get(
            'SSLKEYLOGFILE')  else rootpath + '\\sslkeylog.log'
        clientrandom = self.sock.client_random().encode('hex')
        masterkey = self.sock.master_key().encode('hex')
        with open(sslkeylogfile, 'a+') as nsslog:
         nsslog.write('CLIENT_RANDOM %s %s\n' % (clientrandom, masterkey))

    def _ssl_sock(self):
        self.sslcontext = Context(TLSv1_2_METHOD)
        self.sock = Connection(self.sslcontext,self.sock)
        self.sock.connect((self.host,self.port))
        self.sock.do_handshake()
        self._write_sslkey()


    def send(self):
        sendlen = self.sock.send(self.requests)
        self.response = self.sock.recv(1024)
        print sendlen

    def send(self):
        self.rlist.append(self.sock)
        self.wlist.append(self.sock)
        while True:
            print "====into True===="
            readable,writeable,exceptable= select.select(self.rlist,self.wlist,self.elist,1)
            print readable,writeable,exceptable
            if not (readable or writeable or exceptable):
                print " >>Network is not ready!"
                break
            if writeable:
                sendlen = self.sock.send(self.requests)
                if sendlen == len(self.requests):
                    self.wlist.remove(self.sock)
            if readable:
                try:
                    resp = self.sock.recv(1024)
                    self.response+= resp
                    print len(self.response)
                except ZeroReturnError as zeroerror:
                    print "-->> SSL ",zeroerror.message
                    break
                except SysCallError as syserror:
                    print "-->> SSL ",syserror.message
                    break
                except Exception as e:
                    print "-->> SSL others: ",e.message
                    break
                if len(resp) == 0:
                    #### recv Fin from Server
                    print " >> Recv Fin,break!"
                    break
            if exceptable:
                print " >> Exception,break!!"
                break


    def closeit(self):
        from OpenSSL import SSL
        import sys
        if self.protocoltype == 'ssl':
            self.sock.shutdown()
        self.sock.close()

def generate_requests_list(request,number):
    allrequests = []
    for i in range(number):
        for j in request:
            allrequests.append(j)
    return allrequests

if __name__ == '__main__':
    filenames = ['rstcase.txt']
    requests = readFile(filenames)
    requeststimes = 1
    allrequests = generate_requests_list(requests,requeststimes)
    host = '10.200.6.46'
    port = 80
    concurrent_send(host,port,allrequests)
